/**
 * 自动回复相关服务
 * @authors 杨兴洲（of2502）
 * @date    2017/3/21 14:43
 * @version 1.0
 */
/// <reference path="./reply-service.d.ts" />
import AutoReply from "../model/autoreply";
import KeyWordReply from "../model/keyword";
import logger from "../util/logger";

export default class AutoReplyService {

    /**
     * 获取回复规则
     * @param appID
     * @returns {Promise<any>}
     */
    static async getRules(appID: string): Promise<any> {
        return await AutoReply.findOne({appID}, {"_id": 0, "__v": 0, "createdAt": 0, "updatedAt": 0});
    }

    /**
     * 设置回复规则（All)
     * @param appID
     * @param rules
     * @returns {Promise<any>}
     */
    static async setRules({appID, rules}): Promise<any> {
        return await AutoReply.findOneAndUpdate({appID}, rules, {upsert: true, "new": true});
    }

    /**
     * 删除回复规则
     */
    static async deleteRules(appID: string): Promise<any> {
        let reply = await AutoReply.findOneAndRemove({appID});
        logger.debug(reply);
        await KeyWordReply.remove({appID});
        return;
    }

    /**
     * 更新关注时回复规则
     */
    static async updateAddFriendRule({appID, rule}: setRuleParams): Promise<any> {
        return await AutoReply.findOneAndUpdate(
            {appID},
            {add_friend_autoreply_info: rule},
            {upsert: true, "new": true}
        );
    }

    /**
     * 删除关注时回复规则
     */
    static async deleteAddFriendRule(appID): Promise<any> {
        return await AutoReply.findOneAndUpdate(
            {appID},
            {"$unset": {"add_friend_autoreply_info": 1}},
            {"new": true}
        );
    }

    /**
     * 更新消息时回复规则
     */
    static async updateMessageDefaultRule({appID, rule}: setRuleParams): Promise<any> {
        return await AutoReply.findOneAndUpdate(
            {appID},
            {message_default_autoreply_info: rule},
            {upsert: true, "new": true}
        );
    }

    /**
     * 删除关注时回复规则
     */
    static async deleteMessageDefaultRule(appID): Promise<any> {
        return await AutoReply.findOneAndUpdate(
            {appID},
            {"$unset": {"message_default_autoreply_info": 1}},
            {"new": true}
        );
    }

    /**
     * 获取关键词回复列表
     * @ way1 & way2
     */

    static async getKeywordRuleList(appID): Promise<any[]> {
        // way 1
        let doc: any = await AutoReply.findOne({appID})
            .populate("keyword_autoreply_info.list", {
                "__v": 0,
                "appID": 0,
                "createdAt": 0,
                "updatedAt": 0
            }, null, {sort: {updatedAt: -1}});
        return doc.keyword_autoreply_info.list;

        // way 2
        // return await KeyWordReply.find({appID}, {"_id": 0, "__v": 0})
    }

    /**
     * 获取关键词回复分页列表
     * @page
     * @pageSize
     */
    static async getKeywordRuleListByPage({appID, page = 1, pageSize = 10}): Promise<any> {
        const total = await KeyWordReply.count({appID});
        const list = await KeyWordReply.find({appID}, {
            "__v": 0,
            "appID": 0,
            "createdAt": 0,
            "updatedAt": 0
        })
            .sort({updatedAt: -1})
            .skip(pageSize * (page - 1)).limit(pageSize);
        return {total, list};
    }


    /**
     * 新增关键词回复规则
     * @param appID
     * @param rule
     * @returns {Promise<any>}
     */
    static async createKeywordRule({appID, rule}: setRuleParams): Promise<any> {
        const result: any = await KeyWordReply.create({appID, ...rule});
        await AutoReply.findOneAndUpdate({appID}, {"$push": {"keyword_autoreply_info.list": result._id}});
        return result;
    }

    /**
     * 更新关键词回复规则
     * @param ruleID
     * @param rule
     * @returns {Promise<any>}
     */
    static async updateKeywordRule({ruleID, rule}): Promise<any> {
        let {rule_name, reply_mode, keyword_list_info, reply_list_info} = rule;

        return await KeyWordReply.findByIdAndUpdate(ruleID, {
            rule_name,
            reply_mode,
            keyword_list_info,
            reply_list_info
        });

    }

    /**
     * 删除关键词回复规则
     * @param appID
     * @param ruleID
     * @returns {Promise<any>}
     */
    static async deleteKeywordRule({appID, ruleID}: getRuleParams): Promise<any> {
        // 删除Reply相关ref
        await AutoReply.findOneAndUpdate({appID}, {"$pull": {"keyword_autoreply_info.list": ruleID}});
        return await KeyWordReply.findByIdAndRemove(ruleID);

    }

    /**
     * 获取某个关键词回复规则
     * @param ruleID
     * @returns {Promise<any>}
     */
    static async getKeywordRule({ruleID}: getRuleParams): Promise<any> {
        return await KeyWordReply.findById(ruleID, {"_id": 0, "__v": 0})
    }

    /**
     * 根据关键词匹配查询回复规则
     */
    static async getKeywordRuleByText({appID, text}): Promise<any> {
        let doc: any = await KeyWordReply.aggregate([
            {
                $match: {
                    "appID": appID,
                    "keyword_list_info.type": "text"
                }
            },
            {$unwind: "$keyword_list_info"},
            {
                $match: {
                    "keyword_list_info.match_mode": "equal",
                    "keyword_list_info.content": text
                },
            },
            {$sort: {updatedAt: -1}},
            {$limit: 1}
        ]);
        let replyItem = doc[0];
        // todo: 模糊匹配，等待优化
        if (!replyItem) {  //完全匹配无结果 // 执行模糊匹配
            let doc = await KeyWordReply.aggregate([
                {
                    $match: {
                        "appID": appID,
                        "keyword_list_info.type": "text"
                    }
                },
                {$unwind: "$keyword_list_info"},
                {
                    $match: {
                        "keyword_list_info.match_mode": "contain"
                    }
                },
                {$sort: {updatedAt: -1}},
            ]);
            replyItem = doc.find((item: any) => text.indexOf(item.keyword_list_info.content) > -1);
        }
        if (!replyItem) return [];// 无结果
        if (replyItem.reply_mode === "random_one") {
            const index = Math.floor(Math.random() * replyItem.reply_list_info.length);
            logger.debug("随机回复", index);
            return [replyItem.reply_list_info[index]];
        }
        if (replyItem.reply_mode === "reply_all") {
            return replyItem.reply_list_info;
        }
    }
}
